package site.yunnong.atvris.admin.service.impl;

import io.jsonwebtoken.lang.Collections;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import site.yunnong.atvris.dao.admin.domain.AdminDetails;
import site.yunnong.atvris.dao.admin.form.RegisterForm;
import site.yunnong.atvris.dao.admin.service.SysAdminManageService;
import site.yunnong.atvris.dao.common.util.LocalAssert;
import site.yunnong.atvris.dao.security.util.JwtTokenUtil;
import site.yunnong.atvris.dao.mapper.SysAdminMapper;
import site.yunnong.atvris.dao.model.SysAdmin;
import site.yunnong.atvris.dao.model.SysAdminExample;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * @author ZJH
 */
@Slf4j
@Service
public class SysAdminManageServiceImpl implements SysAdminManageService {

    @Resource
    private JwtTokenUtil jwtTokenUtil;

    @Resource
    private SysAdminMapper sysAdminMapper;
    @Resource
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadAdminByUsername(String username) {
        SysAdmin admin = getAdminByUsername(username);
        if (admin != null) {
            return new AdminDetails(admin);
        }
        throw new UsernameNotFoundException("用户名不存在");
    }

    @Override
    public SysAdmin getAdminByUsername(String username) {
        SysAdminExample example = new SysAdminExample();
        example.createCriteria().andUsernameEqualTo(username);
        List<SysAdmin> admins = sysAdminMapper.selectByExample(example);
        if (!Collections.isEmpty(admins)) {
            return admins.get(0);
        }
        return null;
    }

    @Override
    public String register(RegisterForm form) {
        String username = form.getUsername();
        String password = form.getPassword();
        String nickname = form.getNickname();
        // 检验username
        SysAdmin adminByUsername = getAdminByUsername(username);
        LocalAssert.notNull(adminByUsername, "该用户已存在");
        // 检查nickname
        SysAdmin adminByNickname = getAdminByNickname(nickname);
        LocalAssert.notNull(adminByNickname, "该昵称已存在");
        int count = createAdmin(username, password, nickname);
        LocalAssert.notZero(count, "添加管理员失败");
        return login(username, password);
    }

    @Override
    public String login(String username, String password) {
        String token;
        try {
            UserDetails userDetails = loadAdminByUsername(username);
            LocalAssert.notNull(userDetails, "用户名不存在");

            if (!passwordEncoder.matches(password, userDetails.getPassword())) {
                throw new BadCredentialsException("密码错误");
            }
            if (!userDetails.isEnabled()) {
                throw new BadCredentialsException("该账户已被封禁");
            }
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authentication);
            token = jwtTokenUtil.generateToken(userDetails);
        } catch (AuthenticationException e) {
            log.warn("登录异常：{}", e.getMessage());
            throw e;
        }
        return token;
    }

    @Override
    public SysAdmin getAdminById(Long id) {
        return sysAdminMapper.selectByPrimaryKey(id);
    }

    private int createAdmin(String username, String password, String nickname) {
        SysAdmin admin = new SysAdmin();
        admin.setUsername(username);
        admin.setPassword(passwordEncoder.encode(password));
        admin.setNickname(nickname);
        admin.setStatus(1);
        admin.setRegisterTime(new Date());
        return sysAdminMapper.insertSelective(admin);
    }

    private SysAdmin getAdminByNickname(String nickname) {
        SysAdminExample example = new SysAdminExample();
        example.createCriteria().andNicknameEqualTo(nickname);
        List<SysAdmin> admins = sysAdminMapper.selectByExample(example);
        if (!Collections.isEmpty(admins)) {
            return admins.get(0);
        }
        return null;
    }
}
